<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<link title="Catapult doc style" rel="stylesheet" href="doc.css" type="text/css" />
<title>openMSX Catapult - Settings Framework</title>
</head>

<body>

<h1>openMSX Catapult - Settings Framework</h1>

<h2>Definition of Setting</h2>

<p>
openMSX uses settings for both persistent user preferences and non-persistent configuration items. A setting has the following properties:
</p>
<ul>
<li>name</li>
<li>type</li>
<li>current value</li>
<li>default value</li>
<li>range</li>
<li>persistent or not</li>
<li>help text</li>
</ul>
<p>
For some types (such as string) the range is always the full type: any string is possible. For ordered types (int, float) range is a minimum and maximum value. For enumerations, range is the list of possible values.
</p>
<p>
Both the current value and the range are dynamic. An example of a dynamic range is the "videosource" setting: if a GFX9000 cartridge is inserted, an additional video source becomes available.
</p>
<p>
Setting existence is also dynamic: for example sound settings such as volume and balance exist for each sound device and sound devices can come and go at runtime. Another example is the firmware setting, which is only available on machines that have indeed switchable firmware.
</p>

<h2>Requirements for Setting Support in Catapult</h2>

<p>
Much of the functionality of Catapult consists of controlling openMSX settings. Therefore, we want to have a framework that offers an easy way to observe and modify settings.
</p>
<p>
Here is an overview of how Catapult should handle the different setting properties:
</p>
<dl>
<dt>name</dt>
<dd>Settings are identified by their name. If a setting name changes, the Catapult code must be updated to match.</dd>
<dt>type</dt>
<dd>The setting type that Catapult expects must match the type of the setting in openMSX: a checkbox can represent a boolean setting, but not a string setting. If a setting type changes, the Catapult code must be updated to match.</dd>
<dt>current value</dt>
<dd>Catapult must support the current value changing at runtime. Value changes can be initiated by either Catapult or openMSX.</dd>
<dt>default value</dt>
<dd>Catapult must support resetting a setting to its default value. However, this does not necessarily mean that Catapult has to know that default value.</dd>
<dt>range</dt>
<dd>Catapult must support the range changing at runtime. Range changes are always initiated by openMSX.</dd>
<dt>persistent or not</dt>
<dd>Catapult does not have to know whether a setting is persistent.</dd>
<dt>help text</dt>
<dd>The openMSX help text for a setting can be used in Catapult, to avoid duplication of these texts in source code. The help texts do not change at runtime.</dd>
</dl>
<p>
All communication between Catapult and openMSX is asynchronous. This means that reading a setting will not immediately return an answer. The framework should offer a mechanism to deliver the answer when it arrives. Additionally, Catapult can subscribe to updates from openMSX, which arrive in Catapult at arbitrary moments.
</p>
<p>
Typically there is a widget or set of widgets to control a particular setting. The framework must offer a way to keep the value of a widget synchronized to the value of the setting in openMSX: the widget's value must get updated when the setting's value changes and vice versa. This mechanism must avoid oscillation that can happen because of the latency of the asynchronous communication channel with openMSX.
</p>
<p>
In addition to synchronizing the current value, there must be a mechanism to synchronize the current range: if openMSX reports a change in range, the widget must be reconfigured accordingly. Also "revert to default value" must be easy to trigger by a widget.
</p>
<p>
Settings may stop or start to exist when a machine is changed. It must be possible for a widget to be connected to a certain setting in the current machine. When a switch from an old machine to a new machine occurs, the widget must automatically be synchronized (and stay synchronized) to the same setting in the new machine. The cases where a setting exists in the old machine but not in the new machine or vice versa must be supported as well.
</p>

<h2>Design</h2>

<h3>Setting Proxies</h3>
<p>
Catapult will keep a proxy object for every setting that it is interested in. There will be a central registry of setting proxies, to make sure there is at most one proxy for each openMSX setting.
</p>
<p>
Setting properties (both static and dynamic) are fetched from openMSX. Catapult's view of a setting can be in one of the following states:
</p>
<dl>
<dt>unknown</dt>
<dd>It is not known whether the setting currently exists; this implies that the current properties are not known either.</dd>
<dt>known</dt>
<dd>The setting currently exists and all its properties are known.</dd>
<dt>non-existant</dt>
<dd>The setting currently does not exist.</dd>
</dl>
<p>
Note that "currently" refers to Catapult's view of the setting. Because of the asynchronous nature of the control connection, openMSX might temporarily have a different view.
</p>
<p>
It would be possible to query setting properties one at a time, in which case the "known" state would be split into several new states. However, this complicates things without offering an advantage.
</p>
<p>
Some settings exist per machine. For those settings, the setting proxy will reflect the setting from the current machine. Therefore, on a machine change settings can go in or out of existance, or change value.
</p>

<h3>Widgets</h3>

<p class="todo">
We should be able to handle the fact that different widget types have different signals (names and signatures) for 'value changed' and different methods to set a value (e.g. in a ComboBox for EnumSettings, you have to find the proper index and set that as current).
</p>
<p class="todo">
We should take into account that we have to convert types in our setting code. E.g. Slider widgets do not support floats. We have to convert to ints and back to floats for this. Other (small) conversions need to take place for booleans in checkboxes, e.g.
</p>
<p class="todo">
Filename setting: can we use it to do something clever with a file dialog?
</p>

<h2>Issues with Old Design</h2>

<ul>
<li>Settings are sometimes getting registered before the connection is up. This means information cannot be retrieved of the setting and the actual setting cannot be created.</li>
<li>Settings that are not available immediately lead to problems: code that registers a setting and then connects to it, or retrieves it via a getter method gets an incomplete or non-existing setting. There is currently no event that tells this code that the setting is ready to use, nor is the code prepared to handle this situation at all (it assumes a very synchronous behaviour: registration means it exists).</li>
<li>At registration you have to specify the type, while the type is also already retrieved shortly afterwards, when the rest of the settings data is retrieved. It looks and feels superfluous to specify data that is already going to be received from openMSX.</li>
<li>The code that retrieves the setting properties (there were multiple queries, e.g. for setting info itself and for the help text) is chain-linked, meaning a brittle construction.</li>
<li>No support for changing ranges of settings or settings that exist in one machine and not in another (changing availability of settings).</li>
</ul>


<p class="version">
$Id$
</p>

</body>
</html>
